/**
 * 用于实现动态填写多条数据的活动表格
 *
 * @author: DingYi
 * @Date: 2018/12/25
 * @Description: 实现的基本功能有如下：
 * 1.将html元素初始化为activeTable。并创建一条原始行（无数据）。
 * 2.可以根据配置项加载出表格的表头显示以及每行的input的name属性。
 * 3.可以动态的添加行，删除行，行的上下移动
 */
(function($){
    function ActiveTable(div, options){
        var target = this.target = $(div);
        this.default = {
            idField: 'id',
            idFieldWidth: 30,
            index:"序号",
            optionButton: true,
            hiddenInputs: [
                {name: "hidden1"}
            ],
            columns: [
                {field: 'value1', isInput: true, title: '标题1', width: 300, height: 30, type: 'text', option: '', class: 'easyui-textbox'},
                {field: 'value2', isInput: true, title: '标题2', width: 300, height: 30, type: 'text', option: '', class: 'easyui-textbox'}
            ]
        }
        this.columns_default = {
            field: 'value',
            isInput: true,
            title: '标题',
            width: 300,
            height: 30,
            type: 'text',
            option: '',
            class: 'easyui-textbox'
        }
        if(options){
            //对options中的columns继承默认值
            if(options.columns.length > 0){
                for(var i in options.columns){
                    //深层复制用户的columns的设置
                    var tempOption = $.extend(true, {}, options.columns[i]);
                    //加上默认的设置后再设置为用户的设置
                    $.extend(options.columns[i], this.columns_default);
                    $.extend(options.columns[i], tempOption);
                }
            }
            this.option = options;
        }else{
            this.option = this.parseOption($(div).attr("option"));
        }
        this.init();
        //将ActiveTable作为data绑定在div上
        target.data("dyActiveTable" ,this);
    }

    ActiveTable.prototype = {
        //activeTable的初始化方法，将option设置在default设置的基础上添加/覆盖，根据新的option去生成新的Table
        init: function(){
            //在div中创建一个新的table
            var target = this.target.append('<table class="dy-activeTable-table"></table>');
            this.table = target.find(".dy-activeTable-table");
            //获取新的option
            var option = this.option = $.extend({},this.default,this.option);
            //设置表头
            this.setHead();
            //执行一次addLine()
            this.addLine();
        },
        //解析由attr中获取到的option属性
        parseOption: function(option){
            if(option && option != ""){
                var opts = {};
                var keyValues = option.split(";");
                for(var index in keyValues){
                    var keyValue = keyValues[index].split(":");
                    opts[keyValue[0]] = keyValue[1];
                }
                return opts;
            }
        },
        //设置表头
        setHead: function(){
            var lineHtml = '<tr>';
            var columns = this.option.columns;
            //设置表头信息
            lineHtml += '<th><div style="width: '+ this.option.idFieldWidth +'px !important;">'+ this.option.index +'</div></th>';
            for(var i in columns){
                lineHtml += '<th><div style="width: '+ columns[i].width +'px !important;">'+ columns[i].title +'</th>'
            }
            //添加此行的操作栏
            if(this.option.optionButton){
                lineHtml += '<th><div style="min-width: 150px !important;">操作</div></th>'
            }
            lineHtml += '</tr>';
            $(lineHtml).appendTo(this.table);
        },
        //添加一行的方法
        addLine: function(index, target, dataJson, noSort, editable){
            if(!index){
                index = 0;
            }
            var lineHtml = '<tr class="dataTableRow">';
            var columns = this.option.columns;
            var hiddenInputs = this.option.hiddenInputs;
            //拼接一行的数据
            if(editable !== false){
                //若是正常的情况，则生成正常的input框
                //行首的隐藏id项和序号,以及其他隐藏字段
                lineHtml += '<td align="center"><input class="hiddenIndexInput" type="hidden" value="'+ index +'">' +
                    //若要添加的dataJson中有ID项，则默认设置value为该dataJson中ID项的value
                    '<input type="hidden" class="dataInput" name="'+ this.option.idField +'" value="'+ ((dataJson&&dataJson[this.option.idField]) ? dataJson[this.option.idField] : "") +'">';
                for(var j in hiddenInputs){
                    //若要添加的dataJson中有对应隐藏项，则默认设置value为该dataJson中对应隐藏项的value
                    lineHtml += '<input type="hidden" class="dataInput" name="'+ hiddenInputs[j].name +'" value="'+ ((dataJson&&dataJson[hiddenInputs[j].name]) ? dataJson[hiddenInputs[j].name] : "") +'">';
                }
                lineHtml += '<span class="trIndex">'+ (index + 1 - 0) +'</span></td>';
                for(var i in columns){
                    //判断该字段是否是填入的字段，若是，生成输入框，若否，则生成span标签包装，内容显示支持字段之间的数学运算
                    if(columns[i].isInput){
                        lineHtml += '<td align="center"><input class="'+ columns[i].class +'" class="dataInput" type="'+ columns[i].type +
                            '" name="'+ columns[i].field +'" data-options="'+ columns[i].option +
                            '" style="width:'+ (columns[i].width) +'px; height: '+ columns[i].height +'px"' +
                            //若要添加的dataJson中有对应数据项，则默认设置value为该dataJson中对应数据项的value
                            'value="'+ ((dataJson&&dataJson[columns[i].field]) ? dataJson[columns[i].field] : "") +'"/></td>'
                    }else{
                        var value;
                        if(!columns[i].calculate){
                            value = ((dataJson&&dataJson[columns[i].field]) ? dataJson[columns[i].field] : "");
                            lineHtml += '<td align="center">'+ value +'</td>';
                            continue;
                        }
                        if(columns[i].calculate == "plus"){
                            value = 0;
                            for(var j in columns[i].calculateColumns){
                                value += ((dataJson&&dataJson[columns[i].calculateColumns[j]]) ? dataJson[columns[i].calculateColumns[j]] : 0);
                            }
                        }
                        if(columns[i].calculate == "multiply"){
                            value = 1;
                            for(var j in columns[i].calculateColumns){
                                value = value * ((dataJson&&dataJson[columns[i].calculateColumns[j]]) ? dataJson[columns[i].calculateColumns[j]] : 0);
                            }
                        }
                        if(columns[i].calculate == "join"){
                            value = "";
                            for(var j in columns[i].calculateColumns){
                                value += "" + ((dataJson&&dataJson[columns[i].calculateColumns[j]]) ? dataJson[columns[i].calculateColumns[j]] : "");
                            }
                        }
                        lineHtml += '<td class="table-row-cell-calculate" calculateType="'+ columns[i].calculate +'" calculateColums="'+ columns[i].calculateColumns +'" align="center">'+ value.toFixed(2) +'</td>'
                    }
                }
                //添加此行的操作栏
                if(this.option.optionButton){
                    lineHtml += '<td>' +
                        '<span class="table-row-option" option="add"><span class="panel-icon row-add"></span></span>' +
                        '<span class="table-row-option" option="delete"><span class="panel-icon row-remove"></span></span>' +
                        '<span class="table-row-option" option="up"><span class="panel-icon row-up"></span></span>' +
                        '<span class="table-row-option" option="down"><span class="panel-icon row-down"></span></span>' +
                        '</td>';
                }
                lineHtml += '</tr>';
            }else{
                //用于做展示时的行数据
                lineHtml += '<td align="center"><span class="trIndex">'+ (index + 1 - 0) +'</span></td>';
                for(var i in columns){
                    var value = ((dataJson&&dataJson[columns[i].field]) ? dataJson[columns[i].field] : "");
                        lineHtml += '<td align="center">'+ value +'</td>';
                }
                //添加此行的操作栏
                if(this.option.optionButton){
                    lineHtml += '<td>' +
                        '<span class="table-row-option" option="add"><span class="panel-icon row-add"></span></span>' +
                        '<span class="table-row-option" option="delete"><span class="panel-icon row-remove"></span></span>' +
                        '<span class="table-row-option" option="up"><span class="panel-icon row-up"></span></span>' +
                        '<span class="table-row-option" option="down"><span class="panel-icon row-down"></span></span>' +
                        '</td>';
                }
                lineHtml += '</tr>';
            }
            var targetObj = $(lineHtml);
            if(target){
                target.after(targetObj);
            }else{
                targetObj.appendTo(this.table);
            }
            targetObj.data("row", dataJson);
            //进行控件的重新排序
            if(!noSort){
                this.sortIndex();
            }
            //对ui插件重新渲染
            $.parser.parse(targetObj);
            //对操作按钮绑定事件
            this.bindEvent(targetObj);
        },
        //删除一行的方法
        removeLine: function(target){
            //先执行删除前的事件
            var beforeRemove = this.option.beforeRemove;
            //删除操作，需要将row对象作为参数传递到beforeRemove方法中
            var row = target.data("row");
            if(beforeRemove != null && beforeRemove.call(this, row) === false){
               return false;
            }
            var $dataTableRow = $(".dataTableRow");
            //只剩一行的时候不能删除
            if($dataTableRow.length > 0){
                target.remove();
                //进行控件的重新排序
                this.sortIndex();
            }
            return true;
        },
        //上移一行的方法
        upLine: function(target){
            var $preRow = target.prev();
            if(!$preRow || !$preRow.hasClass("dataTableRow")){
                return;
            }
            $preRow.before(target);
            //进行控件的重新排序
            this.sortIndex();
        },
        downLine: function(target){
            var $next = target.next();
            if(!$next || !$next.hasClass("dataTableRow")){
                return;
            }
            $next.after(target);
            //进行控件的重新排序
            this.sortIndex();
        },
        //对新加的一行数据进行绑定事件
        bindEvent: function(jq){
            var activeTableThis = this;
            //判断是否需要绑定操作按钮事件
            if(this.option.optionButton){
                jq.find(".table-row-option").click(function(){
                    var rowTr = $(this).closest("tr");
                    var index = rowTr.find(".hiddenIndexInput").val();
                    var optionType = $(this).attr("option");
                    //绑定添加事件
                    if(optionType == "add"){
                        activeTableThis.addLine(index-0+1, rowTr);
                    }
                    //绑定删除事件
                    if(optionType == "delete"){
                        activeTableThis.removeLine(rowTr);
                    }
                    //绑定上移事件
                    if(optionType == "up"){
                        activeTableThis.upLine(rowTr);
                    }
                    //绑定下移事件
                    if(optionType == "down"){
                        activeTableThis.downLine(rowTr);
                    }
                });
            }
            //绑定需要计算的单元格的相关input控件改变值时重新计算的方法
            var data = 1;
            jq.find(".table-row-cell-calculate").each(function(){
                var calculateColums = $(this).attr("calculateColums").split(",");
                var target = $(this);
                for(var i in calculateColums){
                    $(this).parent().find("input[textboxname='"+ calculateColums[i] +"']").textbox("textbox").blur(function(){
                        data += 1;
                        activeTableThis.calculate(target);
                    });
                }
            });
        },
        //重新对所有的行以及行内的input的name进行标号
        sortIndex: function(){
            var $allRows = $(".dataTableRow");
            $allRows.each(function(index){
                //重新设置隐藏的index和显示的index
                $(this).find(".hiddenIndexInput").val(index);
                $(this).find(".trIndex").html(index-0+1);
            });
        },
        /**
         * 执行单元格计算
         * @param $calcuCell
         */
        calculate: function($calcuCell){
            var calculateType = $calcuCell.attr("calculateType");
            var calculateColums = $calcuCell.attr("calculateColums").split(",");
            var value;
            if(calculateType == "plus"){
                value = 0;
                for(var i in calculateColums){
                    var tempValue = $calcuCell.parent().find("input[name='"+ calculateColums[i] +"']").val();
                    value += (tempValue ? tempValue : 0).toFixed(2);
                }
            }
            if(calculateType == "multiply"){
                value = 1;
                for(var i in calculateColums){
                    var tempValue = $calcuCell.parent().find("input[name='"+ calculateColums[i] +"']").val();
                    value = (value * (tempValue ? tempValue : 0)).toFixed(2);
                }
            }
            if(calculateType == "join"){
                value = "";
                for(var i in calculateColums){
                    var tempValue = $calcuCell.parent().find("input[name='"+ calculateColums[i] +"']").val();
                    value += "" + (tempValue ? tempValue : "");
                }
            }
            $calcuCell.html(value);
        }
    }

    $.fn.extend({
        dyActiveTable:function(options, param){
            if (typeof options == 'string'){
                var method = $.fn.dyActiveTable.methods[options];
                if (method){
                    return method(this, param);
                }else{
                    return;
                }
            }

            this.each(function(){
                new ActiveTable(this, options);
            })
            return this;
        }
    });

    $.fn.dyActiveTable.methods = {
        addLine : function(jq, param){
            var dataJson = (param && param[0]) ? param[0] : {};
            var noSort = (param && param[1]) ? param[1] : false;
            jq.each(function(){
                var dyActiveTable = $(this).data("dyActiveTable");
                
                dyActiveTable.addLine(null, null, dataJson, noSort);
            });
        },
        removeLineById : function(jq, param){
            jq.each(function () {
                var dyActiveTable = $(this).data("dyActiveTable");
                var delRow = $(".dataTableRow").find("input[value='"+ param +"']").closest(".dataTableRow");
                delRow.remove();
                var $otherRows = $(".dataTableRow");
                if($otherRows.length == 0){
                    dyActiveTable.addLine();
                }
                dyActiveTable.sortIndex();
            });
        },
        removeLine : function(jq, param){
            var start , end;
            jq.each(function () {
                var dyActiveTable = $(this).data("dyActiveTable");
                var $rows = $(".dataTableRow");
                start = (param && param[0]) ? param[0] : 1;
                end = (param && param[1]) ? param[1] : $rows.length;
                $rows.each(function(index){
                    if(start <= index + 1 && index + 1 <= end){
                       $(this).remove();
                    }
                });
                var $otherRows = $(".dataTableRow");
                if($otherRows.length == 0){
                    dyActiveTable.addLine();
                }
                dyActiveTable.sortIndex();
            });
        },
        loadData : function(jq, param) {
            var jsonList, editable;
            jsonList = param.dataList;
            editable = param.editable;
            jq.each(function(){
                var dyActiveTable = $(this).data("dyActiveTable");
                for(var i in jsonList){
                    dyActiveTable.addLine(null, null, jsonList[i], null, editable);
                }
                jq.dyActiveTable("removeLine", [1, 1]);
            });
        },
        sortIndex : function(jq){
            jq.each(function(){
                var dyActiveTable = $(this).data("dyActiveTable");
                dyActiveTable.sortIndex();
            });
        }
    }
})(jQuery)

//页面加载完毕后去扫描页面元素
$(function(){
    $(".dy-activeTable").dyActiveTable();
});